
#include"c_aritmetico.h"


#define G1Q 0x20000000
#define GMED 0x40000000
#define G3Q 0x60000000
#define GMAX 0x7FFFFFFF	



c_aritmetico::c_aritmetico()
{
	mBitCount=0;
	mBitBuffer=0;

	pPiso=0;
	pTecho=GMAX;
	pEscala=0;
	
	mBuffer=0;
	mStep=0;
}

void c_aritmetico::SetFile(fstream*file)

{
	mFile=file;
}

void c_aritmetico::SetBit(const unsigned char bit)
{
	mBitBuffer=(mBitBuffer<<1)|bit;
	mBitCount++;

	if(mBitCount==8)
	{	
		mFile->write(reinterpret_cast<char*>(&mBitBuffer),sizeof(mBitBuffer));
		mBitCount=0;
	}
}


unsigned char c_aritmetico::GetBit()
{
	if(mBitCount==0)
	{
		if(!(mFile->eof()))
			mFile->read(reinterpret_cast<char*>(&mBitBuffer),sizeof(mBitBuffer));
		else
			mBitBuffer=0;

		mBitCount=8;
	}

	unsigned char bit=mBitBuffer>>7;
	mBitBuffer<<=1;
	mBitCount--;

	return(bit);
}



void c_aritmetico::comprimir_finalizar()
{
	if(pPiso<G1Q)
	{
		SetBit(0);
		for(unsigned int i=0;i<pEscala+1;i++)SetBit(1);
	}
	else SetBit(1);
	
	while(mBitCount!=0)SetBit(0);

	
}


void c_aritmetico::descomprimir_iniciar()

{

	for(unsigned int i=0;i<31;i++)mBuffer=(mBuffer<<1)|GetBit();
}


unsigned int c_aritmetico::descomprimirTarget(const unsigned int total)

{

	mStep=(pTecho-pPiso+1)/total;
	return(mBuffer-pPiso)/mStep;	
}






void c_aritmetico::comprimir(const unsigned int low_count,const unsigned int high_count,const unsigned int total)

{

int salida=0;
	
mStep=(pTecho-pPiso+1)/total;
pTecho=pPiso+mStep*high_count-1;
pPiso=pPiso+mStep*low_count;
	
while(!salida)
	{
		if(pTecho<GMED)
		{
		SetBit(0);			
		pPiso<<=1;
		pTecho<<=1;pTecho++;
		for (;pEscala>0;pEscala--)SetBit(1);				
		}
		else if(pPiso>=GMED)
		{
		SetBit(1);			
		pPiso-=GMED;pPiso<<=1;
		pTecho-=GMED;pTecho<<=1;pTecho++;
		for (;pEscala>0;pEscala--)SetBit(0);								
		} else salida=1;
	}

while((pTecho<G3Q)&&(G1Q<=pPiso))
    {
	pEscala++;
	pPiso-=G1Q;pPiso<<=1;
	pTecho-=G1Q;pTecho<<=1;pTecho++;	
    }




}



void c_aritmetico::descomprimir(const unsigned int low_count,const unsigned int high_count)
{
int salida=0;

pTecho=pPiso+mStep*high_count-1;
pPiso=pPiso+mStep*low_count;

while(!salida)
	{
		if(pTecho<GMED)
		{
			pPiso<<=1;
			pTecho<<=1;pTecho++;
			mBuffer=2*mBuffer+GetBit();
			pEscala=0;
		}
		else if(pPiso>=GMED)
		{
			pPiso-=GMED;pPiso<<=1;
			pTecho-=GMED;pTecho<<=1;pTecho++;
			mBuffer=2*(mBuffer-GMED)+GetBit();
			pEscala=0;	
		} else salida=1;
	}

while((pTecho<G3Q)&&(G1Q<=pPiso))
    {
    pEscala++;
    pPiso-=G1Q;pPiso<<=1;
    pTecho-=G1Q;pTecho<<=1;pTecho++;
    mBuffer=2*(mBuffer-G1Q)+GetBit();		
    }
    
}
